<script setup lang="ts">
import * as Cesium from 'cesium'
import type { Viewer, Cartesian2, Entity } from 'cesium'
import satstationImg from '@/assets/images/satstation.png'
import satelliteStations from '@/data/satelliteStations.json'
import { useStationsStore } from '@/store'
import useSkyBox from '@/hooks/useSkyBox'

interface StationEntity extends Entity {
  stationInfo?: StationData
}

const stationsStore = useStationsStore()
const stations: StationMap = satelliteStations
const options: Viewer.ConstructorOptions = {
  selectionIndicator: false, //关闭点击方框
  infoBox: false, //关闭属性默认弹窗
  geocoder: false, // 地理位置查询定位控件
  homeButton: false, // 默认相机位置控件
  timeline: false, // 时间滚动条控件
  navigationHelpButton: false, // 默认的相机控制提示控件
  fullscreenButton: false, // 全屏控件
  scene3DOnly: true, // 每个几何实例仅以3D渲染以节省GPU内存
  baseLayerPicker: false, // 底图切换控件
  shadows: true,
  animation: false, // 控制场景动画的播放速度控件
  orderIndependentTranslucency: false
}
const _stationEntities: { [key: string]: Cesium.Entity } = {}
let highlightedEntity: StationEntity
const imageList: Record<string, { default: string }> = import.meta.glob('@/assets//skyboxs/*.jpg', { eager: true })
const imageLists = Object.keys(imageList).map((filePath) => {
  const fileName = filePath
    .split('/')
    .pop()
    ?.replace(/\.\w+$/, '')
  return { name: fileName, path: filePath }
})
const imageMap = imageLists.reduce(
  (acc, { name, path }) => {
    if (name) acc[name] = path
    return acc
  },
  {} as Record<string, string>
)

function addSatelliteStations() {
  Object.keys(stations).forEach((key) => {
    const station = stations[key]
    const stationEntity: StationEntity = window.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(parseFloat(station.Longitude), parseFloat(station.Latitude), 100),
      id: `station-${key}`,
      name: key,
      point: {
        pixelSize: 5,
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(30000000, 100000000),
        disableDepthTestDistance: 1000000,
        color: new Cesium.Color(255, 127, 39)
      },
      billboard: {
        image: satstationImg,
        width: 16,
        height: 24,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(0, -10),
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 30000000),
        eyeOffset: new Cesium.Cartesian3(0, 0, -100000),
        scaleByDistance: new Cesium.NearFarScalar(100, 2, 30000000, 0.5)
      }
    })
    stationEntity.stationInfo = { ...station }
    _stationEntities[key] = stationEntity
  })
}

function pickStation() {
  const pickStationHandler = new Cesium.ScreenSpaceEventHandler(window.viewer.scene.canvas)
  pickStationHandler.setInputAction((event: { position: Cartesian2 }) => {
    const feature = window.viewer.scene.pick(event.position)
    if (Cesium.defined(feature)) {
      if (Object.prototype.hasOwnProperty.call(feature, 'id') && feature.id instanceof Cesium.Entity) {
        if (feature.id._id.startsWith('station-')) {
          const name = feature.id._id.substring(8, feature.id._id.length)
          const entity: StationEntity = _stationEntities[`${name}`]
          if (highlightedEntity && highlightedEntity !== entity) {
            highlightedEntity.billboard!.color = new Cesium.ConstantProperty(Cesium.Color.WHITE)
          }
          entity.billboard!.color = new Cesium.ConstantProperty(Cesium.Color.RED)
          stationsStore.setStationData({ name, ...entity.stationInfo } as StationData)
          highlightedEntity = entity
        }
      }
    } else {
      if (highlightedEntity) highlightedEntity.billboard!.color = new Cesium.ConstantProperty(Cesium.Color.WHITE)
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}

onMounted(() => {
  window.viewer = new Cesium.Viewer('cesiumContainer', options)
  window.viewer.scene.globe.depthTestAgainstTerrain = true // 开启深度测试
  addSatelliteStations()
  pickStation()
  useSkyBox(
    {
      positiveX: imageMap.tycho2t3_80_px,
      negativeX: imageMap.tycho2t3_80_mx,
      positiveY: imageMap.tycho2t3_80_py,
      negativeY: imageMap.tycho2t3_80_my,
      positiveZ: imageMap.tycho2t3_80_pz,
      negativeZ: imageMap.tycho2t3_80_mz
    },
    {
      positiveX: imageMap.Right,
      negativeX: imageMap.Left,
      positiveY: imageMap.Front,
      negativeY: imageMap.Back,
      positiveZ: imageMap.Up,
      negativeZ: imageMap.Down
    }
  )
})
</script>

<template>
  <div id="cesiumContainer" class="absolute-full"></div>
</template>

<style lang="scss" scoped></style>
